package com.gateway.plugin.security.oauth2.client;

import com.gateway.security.common.authentication.client.ClientPrincipal;
import com.gateway.security.common.authentication.client.ClientPrincipalConverter;
import com.google.common.collect.Sets;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @program: api-gateway
 * @description:
 * @author: YuKai Fan
 * @create: 2025/2/12 20:11
 **/
public class OAuth2ClientPrincipalConverter implements ClientPrincipalConverter {
    private final static String CLIENT_ID = "clientId";
    private final static String CLIENT_NAME = "clientName";
    private final static String AUTHORITIES = "authorities";

    @Override
    public Mono<ClientPrincipal> convert(Map<String, Object> claims) {
        OAuth2Client.Builder builder = OAuth2Client.Builder.builder();
        for (Map.Entry<String, Object> entry : claims.entrySet()) {
            if (CLIENT_ID.equals(entry.getKey())) {
                builder.clientId((String) entry.getValue());
            }
            if (CLIENT_NAME.equals(entry.getKey())) {
                builder.clientName((String) entry.getValue());
            }
            if (AUTHORITIES.equals(entry.getKey())) {
                builder.authorities(convertAuthorities(entry.getValue()));
            }
        }
        return Mono.just(builder.build());
    }

    private Set<SimpleGrantedAuthority> convertAuthorities(Object value) {
        Set<SimpleGrantedAuthority> authorities = Sets.newHashSet();
        if (value instanceof List<?> list) {
            for (Object object : list) {
                if (object instanceof String) {
                    authorities.add(new SimpleGrantedAuthority((String) object));
                } else if (object instanceof Map<?, ?> map) {
                    if (map.containsKey("authority")) {
                        authorities.add(new SimpleGrantedAuthority(String.valueOf(map.get("authority"))));
                    }
                }
            }
        }
        return authorities;
    }
}
